#include <string.h>
#include "grid.h"
#include "rowminlex.h"

extern const char bandPrefix416[401][16] = {
{6,7,8,9,1,2,3,7,8,9,1,2,3,4,5,6},{6,7,8,9,1,2,3,7,8,9,1,2,3,4,6,5},{6,7,8,9,1,2,3,7,8,9,1,2,3,5,6,4},{6,7,8,9,1,2,3,7,8,9,1,3,2,4,6,5},
{6,7,8,9,1,2,3,7,8,9,1,3,2,5,4,6},{6,7,8,9,1,2,3,7,8,9,1,3,2,5,6,4},{6,7,8,9,1,2,3,7,8,9,2,3,1,5,6,4},{6,7,8,9,1,2,3,7,8,9,2,3,1,6,4,5},
{6,7,8,9,1,2,3,7,9,8,1,3,2,4,6,5},{6,7,8,9,1,2,3,7,9,8,1,3,2,5,4,6},{6,7,8,9,1,2,3,7,9,8,1,3,2,5,6,4},{6,7,8,9,1,2,3,7,9,8,2,1,3,5,6,4},
{6,7,8,9,1,2,3,7,9,8,2,1,3,6,5,4},{6,7,8,9,1,2,3,7,9,8,2,3,1,5,6,4},{6,7,8,9,1,2,3,7,9,8,2,3,1,6,4,5},{6,7,8,9,1,2,3,8,9,7,2,3,1,5,6,4},
{6,7,8,9,1,2,3,8,9,7,2,3,1,6,4,5},{6,7,8,9,1,3,2,7,8,9,1,2,3,5,4,6},{6,7,8,9,1,3,2,7,8,9,1,3,2,5,4,6},{6,7,8,9,1,3,2,7,8,9,1,3,2,5,6,4},
{6,7,8,9,1,3,2,7,8,9,2,1,3,4,5,6},{6,7,8,9,1,3,2,7,8,9,2,1,3,6,4,5},{6,7,8,9,1,3,2,7,8,9,2,1,3,6,5,4},{6,7,8,9,1,3,2,7,8,9,2,3,1,5,4,6},
{6,7,8,9,1,3,2,7,8,9,2,3,1,5,6,4},{6,7,8,9,1,3,2,8,7,9,2,3,1,5,6,4},{6,7,8,9,2,3,1,7,8,9,1,2,3,6,4,5},{6,7,8,9,2,3,1,7,8,9,1,3,2,5,4,6},
{6,7,8,9,2,3,1,7,8,9,2,3,1,5,6,4},{6,7,8,9,2,3,1,7,8,9,3,1,2,4,5,6},{6,7,8,9,2,3,1,7,9,8,2,1,3,6,4,5},{7,1,8,9,2,3,6,6,8,9,2,3,7,1,4,5},
{7,1,8,9,2,3,6,6,8,9,2,3,7,1,5,4},{7,1,8,9,2,3,6,6,8,9,2,3,7,4,1,5},{7,1,8,9,2,3,6,6,8,9,2,3,7,4,5,1},{7,1,8,9,2,3,6,6,8,9,2,3,7,5,1,4},
{7,1,8,9,2,3,6,6,8,9,2,3,7,5,4,1},{7,1,8,9,2,3,6,6,8,9,2,7,3,1,4,5},{7,1,8,9,2,3,6,6,8,9,2,7,3,1,5,4},{7,1,8,9,2,3,6,6,8,9,2,7,3,4,1,5},
{7,1,8,9,2,3,6,6,8,9,2,7,3,4,5,1},{7,1,8,9,2,3,6,6,8,9,2,7,3,5,1,4},{7,1,8,9,2,3,6,6,8,9,2,7,3,5,4,1},{7,1,8,9,2,3,6,6,8,9,3,2,7,1,4,5},
{7,1,8,9,2,3,6,6,8,9,3,2,7,1,5,4},{7,1,8,9,2,3,6,6,8,9,3,2,7,4,1,5},{7,1,8,9,2,3,6,6,8,9,3,2,7,4,5,1},{7,1,8,9,2,3,6,6,8,9,3,2,7,5,1,4},
{7,1,8,9,2,3,6,6,8,9,3,2,7,5,4,1},{7,1,8,9,2,3,6,6,8,9,3,7,2,1,4,5},{7,1,8,9,2,3,6,6,8,9,3,7,2,1,5,4},{7,1,8,9,2,3,6,6,8,9,3,7,2,4,1,5},
{7,1,8,9,2,3,6,6,8,9,3,7,2,4,5,1},{7,1,8,9,2,3,6,6,8,9,3,7,2,5,1,4},{7,1,8,9,2,3,6,6,8,9,3,7,2,5,4,1},{7,1,8,9,2,3,6,6,8,9,7,2,3,1,4,5},
{7,1,8,9,2,3,6,6,8,9,7,2,3,1,5,4},{7,1,8,9,2,3,6,6,8,9,7,2,3,4,1,5},{7,1,8,9,2,3,6,6,8,9,7,2,3,5,1,4},{7,1,8,9,2,3,6,6,8,9,7,2,3,5,4,1},
{7,1,8,9,2,3,6,6,8,9,7,3,2,1,4,5},{7,1,8,9,2,3,6,6,8,9,7,3,2,1,5,4},{7,1,8,9,2,3,6,6,8,9,7,3,2,4,1,5},{7,1,8,9,2,3,6,6,8,9,7,3,2,5,1,4},
{7,1,8,9,2,3,6,6,8,9,7,3,2,5,4,1},{7,1,8,9,2,3,6,6,9,8,2,3,7,1,4,5},{7,1,8,9,2,3,6,6,9,8,2,3,7,1,5,4},{7,1,8,9,2,3,6,6,9,8,2,3,7,4,1,5},
{7,1,8,9,2,3,6,6,9,8,2,3,7,5,1,4},{7,1,8,9,2,3,6,6,9,8,2,3,7,5,4,1},{7,1,8,9,2,3,6,6,9,8,2,7,3,1,4,5},{7,1,8,9,2,3,6,6,9,8,2,7,3,1,5,4},
{7,1,8,9,2,3,6,6,9,8,2,7,3,4,1,5},{7,1,8,9,2,3,6,6,9,8,2,7,3,5,1,4},{7,1,8,9,2,3,6,6,9,8,2,7,3,5,4,1},{7,1,8,9,2,3,6,6,9,8,3,2,7,1,4,5},
{7,1,8,9,2,3,6,6,9,8,3,2,7,1,5,4},{7,1,8,9,2,3,6,6,9,8,3,2,7,4,1,5},{7,1,8,9,2,3,6,6,9,8,3,2,7,5,4,1},{7,1,8,9,2,3,6,6,9,8,3,7,2,1,4,5},
{7,1,8,9,2,3,6,6,9,8,3,7,2,1,5,4},{7,1,8,9,2,3,6,6,9,8,3,7,2,4,1,5},{7,1,8,9,2,3,6,6,9,8,3,7,2,5,1,4},{7,1,8,9,2,3,6,6,9,8,3,7,2,5,4,1},
{7,1,8,9,2,3,6,6,9,8,7,2,3,1,4,5},{7,1,8,9,2,3,6,6,9,8,7,2,3,1,5,4},{7,1,8,9,2,3,6,6,9,8,7,2,3,4,1,5},{7,1,8,9,2,3,6,6,9,8,7,2,3,5,1,4},
{7,1,8,9,2,3,6,6,9,8,7,3,2,1,4,5},{7,1,8,9,2,3,6,6,9,8,7,3,2,1,5,4},{7,1,8,9,2,3,6,6,9,8,7,3,2,4,1,5},{7,1,8,9,2,3,6,6,9,8,7,3,2,5,1,4},
{7,1,8,9,2,3,6,8,6,9,2,3,7,1,4,5},{7,1,8,9,2,3,6,8,6,9,2,3,7,5,1,4},{7,1,8,9,2,3,6,8,6,9,2,7,3,1,4,5},{7,1,8,9,2,3,6,8,6,9,2,7,3,1,5,4},
{7,1,8,9,2,3,6,8,6,9,2,7,3,4,1,5},{7,1,8,9,2,3,6,8,6,9,2,7,3,5,1,4},{7,1,8,9,2,3,6,8,6,9,3,2,7,1,5,4},{7,1,8,9,2,3,6,8,6,9,3,2,7,4,1,5},
{7,1,8,9,2,3,6,8,6,9,3,2,7,5,1,4},{7,1,8,9,2,3,6,8,6,9,3,7,2,1,4,5},{7,1,8,9,2,3,6,8,6,9,3,7,2,1,5,4},{7,1,8,9,2,3,6,8,6,9,3,7,2,4,1,5},
{7,1,8,9,2,3,6,8,6,9,3,7,2,5,1,4},{7,1,8,9,2,3,6,8,6,9,7,2,3,1,4,5},{7,1,8,9,2,3,6,8,6,9,7,2,3,1,5,4},{7,1,8,9,2,3,6,8,6,9,7,2,3,5,1,4},
{7,1,8,9,2,3,6,8,6,9,7,3,2,1,4,5},{7,1,8,9,2,3,6,8,6,9,7,3,2,1,5,4},{7,1,8,9,2,3,6,8,9,6,2,3,7,1,4,5},{7,1,8,9,2,3,6,8,9,6,2,3,7,1,5,4},
{7,1,8,9,2,3,6,8,9,6,2,3,7,5,1,4},{7,1,8,9,2,3,6,8,9,6,2,7,3,1,4,5},{7,1,8,9,2,3,6,8,9,6,2,7,3,1,5,4},{7,1,8,9,2,3,6,8,9,6,2,7,3,5,1,4},
{7,1,8,9,2,3,6,8,9,6,3,2,7,1,4,5},{7,1,8,9,2,3,6,8,9,6,3,2,7,1,5,4},{7,1,8,9,2,3,6,8,9,6,3,2,7,5,1,4},{7,1,8,9,2,3,6,8,9,6,3,7,2,1,4,5},
{7,1,8,9,2,3,6,8,9,6,3,7,2,1,5,4},{7,1,8,9,2,3,6,8,9,6,3,7,2,5,1,4},{7,1,8,9,2,3,6,8,9,6,7,2,3,1,5,4},{7,1,8,9,2,3,6,8,9,6,7,2,3,5,1,4},
{7,1,8,9,2,3,6,8,9,6,7,3,2,1,5,4},{7,1,8,9,2,3,6,8,9,6,7,3,2,5,1,4},{7,1,8,9,2,3,6,9,6,8,2,3,7,1,5,4},{7,1,8,9,2,3,6,9,6,8,2,3,7,5,1,4},
{7,1,8,9,2,3,6,9,6,8,2,7,3,5,1,4},{7,1,8,9,2,3,6,9,6,8,3,2,7,1,5,4},{7,1,8,9,2,3,6,9,6,8,3,2,7,5,1,4},{7,1,8,9,2,3,6,9,6,8,3,7,2,1,5,4},
{7,1,8,9,2,3,6,9,6,8,3,7,2,5,1,4},{7,1,8,9,2,3,6,9,6,8,7,2,3,1,5,4},{7,1,8,9,2,3,6,9,6,8,7,3,2,1,5,4},{7,1,8,9,2,3,6,9,8,6,2,3,7,1,5,4},
{7,1,8,9,2,3,6,9,8,6,2,7,3,1,5,4},{7,1,8,9,2,3,6,9,8,6,3,2,7,1,5,4},{7,1,8,9,2,3,6,9,8,6,3,7,2,1,5,4},{7,1,8,9,2,6,3,6,8,9,2,3,7,1,4,5},
{7,1,8,9,2,6,3,6,8,9,2,3,7,4,1,5},{7,1,8,9,2,6,3,6,8,9,2,3,7,4,5,1},{7,1,8,9,2,6,3,6,8,9,2,3,7,5,1,4},{7,1,8,9,2,6,3,6,8,9,2,7,3,1,5,4},
{7,1,8,9,2,6,3,6,8,9,2,7,3,4,1,5},{7,1,8,9,2,6,3,6,8,9,2,7,3,4,5,1},{7,1,8,9,2,6,3,6,8,9,2,7,3,5,1,4},{7,1,8,9,2,6,3,6,8,9,2,7,3,5,4,1},
{7,1,8,9,2,6,3,6,8,9,3,2,7,1,5,4},{7,1,8,9,2,6,3,6,8,9,3,2,7,4,1,5},{7,1,8,9,2,6,3,6,8,9,3,2,7,5,1,4},{7,1,8,9,2,6,3,6,8,9,3,2,7,5,4,1},
{7,1,8,9,2,6,3,6,8,9,3,7,2,1,4,5},{7,1,8,9,2,6,3,6,8,9,3,7,2,1,5,4},{7,1,8,9,2,6,3,6,8,9,3,7,2,4,1,5},{7,1,8,9,2,6,3,6,8,9,3,7,2,4,5,1},
{7,1,8,9,2,6,3,6,8,9,3,7,2,5,1,4},{7,1,8,9,2,6,3,6,8,9,7,2,3,1,4,5},{7,1,8,9,2,6,3,6,8,9,7,2,3,1,5,4},{7,1,8,9,2,6,3,6,8,9,7,2,3,4,5,1},
{7,1,8,9,2,6,3,6,8,9,7,3,2,1,4,5},{7,1,8,9,2,6,3,6,8,9,7,3,2,1,5,4},{7,1,8,9,2,6,3,6,8,9,7,3,2,4,1,5},{7,1,8,9,2,6,3,6,8,9,7,3,2,4,5,1},
{7,1,8,9,2,6,3,6,8,9,7,3,2,5,1,4},{7,1,8,9,2,6,3,6,8,9,7,3,2,5,4,1},{7,1,8,9,2,6,3,6,9,8,2,3,7,1,5,4},{7,1,8,9,2,6,3,6,9,8,2,3,7,4,1,5},
{7,1,8,9,2,6,3,6,9,8,2,3,7,4,5,1},{7,1,8,9,2,6,3,6,9,8,2,3,7,5,1,4},{7,1,8,9,2,6,3,6,9,8,2,7,3,1,4,5},{7,1,8,9,2,6,3,6,9,8,2,7,3,4,1,5},
{7,1,8,9,2,6,3,6,9,8,2,7,3,4,5,1},{7,1,8,9,2,6,3,6,9,8,2,7,3,5,1,4},{7,1,8,9,2,6,3,6,9,8,3,2,7,1,4,5},{7,1,8,9,2,6,3,6,9,8,3,2,7,1,5,4},
{7,1,8,9,2,6,3,6,9,8,3,2,7,4,1,5},{7,1,8,9,2,6,3,6,9,8,3,2,7,4,5,1},{7,1,8,9,2,6,3,6,9,8,3,2,7,5,1,4},{7,1,8,9,2,6,3,6,9,8,3,7,2,1,5,4},
{7,1,8,9,2,6,3,6,9,8,3,7,2,4,1,5},{7,1,8,9,2,6,3,6,9,8,3,7,2,5,1,4},{7,1,8,9,2,6,3,6,9,8,3,7,2,5,4,1},{7,1,8,9,2,6,3,6,9,8,7,3,2,1,4,5},
{7,1,8,9,2,6,3,6,9,8,7,3,2,1,5,4},{7,1,8,9,2,6,3,6,9,8,7,3,2,4,5,1},{7,1,8,9,2,6,3,8,6,9,2,3,7,1,5,4},{7,1,8,9,2,6,3,8,6,9,2,3,7,4,1,5},
{7,1,8,9,2,6,3,8,6,9,2,3,7,5,1,4},{7,1,8,9,2,6,3,8,6,9,2,7,3,4,5,1},{7,1,8,9,2,6,3,8,6,9,3,2,7,4,1,5},{7,1,8,9,2,6,3,8,6,9,3,2,7,4,5,1},
{7,1,8,9,2,6,3,8,6,9,3,2,7,5,1,4},{7,1,8,9,2,6,3,8,6,9,3,7,2,1,4,5},{7,1,8,9,2,6,3,8,6,9,3,7,2,1,5,4},{7,1,8,9,2,6,3,8,6,9,3,7,2,5,1,4},
{7,1,8,9,2,6,3,8,9,6,2,3,7,1,4,5},{7,1,8,9,2,6,3,8,9,6,2,3,7,1,5,4},{7,1,8,9,2,6,3,8,9,6,2,3,7,4,5,1},{7,1,8,9,2,6,3,8,9,6,3,2,7,1,4,5},
{7,1,8,9,2,6,3,8,9,6,3,2,7,1,5,4},{7,1,8,9,2,6,3,8,9,6,3,2,7,4,1,5},{7,1,8,9,2,6,3,8,9,6,3,2,7,4,5,1},{7,1,8,9,2,6,3,8,9,6,3,2,7,5,1,4},
{7,1,8,9,2,6,3,8,9,6,3,2,7,5,4,1},{7,1,8,9,2,6,3,8,9,6,3,7,2,1,4,5},{7,1,8,9,2,6,3,8,9,6,3,7,2,1,5,4},{7,1,8,9,2,6,3,8,9,6,3,7,2,4,5,1},
{7,1,8,9,2,6,3,9,6,8,3,2,7,1,4,5},{7,1,8,9,2,6,3,9,6,8,3,2,7,1,5,4},{7,1,8,9,2,6,3,9,6,8,3,2,7,4,1,5},{7,1,8,9,2,6,3,9,6,8,3,2,7,5,1,4},
{7,1,8,9,2,6,3,9,6,8,3,2,7,5,4,1},{7,1,8,9,2,6,3,9,6,8,3,7,2,1,4,5},{7,1,8,9,2,6,3,9,8,6,3,2,7,1,4,5},{7,1,8,9,2,6,3,9,8,6,3,2,7,1,5,4},
{7,1,8,9,2,6,3,9,8,6,3,2,7,4,5,1},{7,1,8,9,3,2,6,6,8,9,2,3,7,4,5,1},{7,1,8,9,3,2,6,6,8,9,2,3,7,5,1,4},{7,1,8,9,3,2,6,6,8,9,2,3,7,5,4,1},
{7,1,8,9,3,2,6,6,8,9,2,7,3,1,4,5},{7,1,8,9,3,2,6,6,8,9,2,7,3,4,5,1},{7,1,8,9,3,2,6,6,8,9,2,7,3,5,4,1},{7,1,8,9,3,2,6,6,8,9,3,2,7,1,5,4},
{7,1,8,9,3,2,6,6,8,9,3,2,7,4,5,1},{7,1,8,9,3,2,6,6,8,9,3,2,7,5,4,1},{7,1,8,9,3,2,6,6,8,9,3,7,2,4,1,5},{7,1,8,9,3,2,6,6,8,9,3,7,2,5,4,1},
{7,1,8,9,3,2,6,6,8,9,7,2,3,1,4,5},{7,1,8,9,3,2,6,6,8,9,7,2,3,4,1,5},{7,1,8,9,3,2,6,6,8,9,7,3,2,1,4,5},{7,1,8,9,3,2,6,6,8,9,7,3,2,4,1,5},
{7,1,8,9,3,2,6,6,8,9,7,3,2,5,1,4},{7,1,8,9,3,2,6,6,8,9,7,3,2,5,4,1},{7,1,8,9,3,2,6,6,9,8,2,3,7,1,4,5},{7,1,8,9,3,2,6,6,9,8,2,3,7,5,4,1},
{7,1,8,9,3,2,6,6,9,8,2,7,3,5,1,4},{7,1,8,9,3,2,6,6,9,8,2,7,3,5,4,1},{7,1,8,9,3,2,6,6,9,8,7,3,2,4,1,5},{7,1,8,9,3,2,6,8,6,9,3,7,2,5,1,4},
{7,1,8,9,6,2,3,6,8,9,2,3,7,1,4,5},{7,1,8,9,6,2,3,6,8,9,2,3,7,1,5,4},{7,1,8,9,6,2,3,6,8,9,2,7,3,1,4,5},{7,1,8,9,6,2,3,6,8,9,2,7,3,1,5,4},
{7,1,8,9,6,2,3,6,8,9,2,7,3,5,4,1},{7,1,8,9,6,2,3,6,8,9,3,2,7,1,4,5},{7,1,8,9,6,2,3,6,8,9,3,2,7,1,5,4},{7,1,8,9,6,2,3,6,8,9,3,7,2,1,4,5},
{7,1,8,9,6,2,3,6,8,9,3,7,2,1,5,4},{7,1,8,9,6,2,3,6,8,9,3,7,2,5,1,4},{7,1,8,9,6,2,3,6,8,9,7,2,3,1,4,5},{7,1,8,9,6,2,3,6,8,9,7,2,3,1,5,4},
{7,1,8,9,6,2,3,6,8,9,7,2,3,4,1,5},{7,1,8,9,6,2,3,6,8,9,7,2,3,4,5,1},{7,1,8,9,6,2,3,6,8,9,7,2,3,5,1,4},{7,1,8,9,6,2,3,6,8,9,7,2,3,5,4,1},
{7,1,8,9,6,2,3,6,8,9,7,3,2,1,4,5},{7,1,8,9,6,2,3,6,8,9,7,3,2,1,5,4},{7,1,8,9,6,2,3,6,8,9,7,3,2,4,1,5},{7,1,8,9,6,2,3,6,8,9,7,3,2,4,5,1},
{7,1,8,9,6,2,3,6,8,9,7,3,2,5,1,4},{7,1,8,9,6,2,3,6,8,9,7,3,2,5,4,1},{7,1,8,9,6,2,3,6,9,8,2,3,7,1,4,5},{7,1,8,9,6,2,3,6,9,8,2,3,7,1,5,4},
{7,1,8,9,6,2,3,6,9,8,2,3,7,5,4,1},{7,1,8,9,6,2,3,6,9,8,2,7,3,1,4,5},{7,1,8,9,6,2,3,6,9,8,2,7,3,1,5,4},{7,1,8,9,6,2,3,6,9,8,3,2,7,1,4,5},
{7,1,8,9,6,2,3,6,9,8,3,2,7,1,5,4},{7,1,8,9,6,2,3,6,9,8,3,2,7,5,1,4},{7,1,8,9,6,2,3,6,9,8,3,7,2,1,4,5},{7,1,8,9,6,2,3,6,9,8,3,7,2,1,5,4},
{7,1,8,9,6,2,3,6,9,8,7,3,2,1,4,5},{7,1,8,9,6,2,3,6,9,8,7,3,2,1,5,4},{7,1,8,9,6,2,3,6,9,8,7,3,2,4,1,5},{7,1,8,9,6,2,3,6,9,8,7,3,2,5,1,4},
{7,1,8,9,6,2,3,6,9,8,7,3,2,5,4,1},{7,1,8,9,6,2,3,8,6,9,2,3,7,1,4,5},{7,1,8,9,6,2,3,8,6,9,2,7,3,1,4,5},{7,1,8,9,6,2,3,8,6,9,2,7,3,1,5,4},
{7,1,8,9,6,2,3,8,6,9,2,7,3,4,5,1},{7,1,8,9,6,2,3,8,6,9,3,2,7,1,5,4},{7,1,8,9,6,2,3,8,6,9,3,7,2,1,4,5},{7,1,8,9,6,2,3,8,6,9,3,7,2,1,5,4},
{7,1,8,9,6,2,3,8,9,6,2,3,7,1,4,5},{7,1,8,9,6,2,3,8,9,6,2,3,7,1,5,4},{7,1,8,9,6,2,3,8,9,6,2,3,7,4,1,5},{7,1,8,9,6,2,3,8,9,6,2,3,7,4,5,1},
{7,1,8,9,6,2,3,8,9,6,2,3,7,5,1,4},{7,1,8,9,6,2,3,8,9,6,2,3,7,5,4,1},{7,1,8,9,6,2,3,8,9,6,3,2,7,1,4,5},{7,1,8,9,6,2,3,8,9,6,3,2,7,1,5,4},
{7,1,8,9,6,2,3,8,9,6,3,2,7,4,1,5},{7,1,8,9,6,2,3,8,9,6,3,2,7,4,5,1},{7,1,8,9,6,2,3,8,9,6,3,2,7,5,1,4},{7,1,8,9,6,2,3,8,9,6,3,7,2,1,4,5},
{7,1,8,9,6,2,3,8,9,6,3,7,2,1,5,4},{7,1,8,9,6,2,3,8,9,6,3,7,2,4,5,1},{7,1,8,9,6,2,3,9,6,8,3,2,7,1,4,5},{7,1,8,9,6,2,3,9,6,8,3,2,7,1,5,4},
{7,1,8,9,6,2,3,9,6,8,3,2,7,4,1,5},{7,1,8,9,6,2,3,9,6,8,3,7,2,1,4,5},{7,1,8,9,6,2,3,9,6,8,3,7,2,1,5,4},{7,1,8,9,6,2,3,9,8,6,3,2,7,1,4,5},
{7,1,8,9,6,2,3,9,8,6,3,2,7,1,5,4},{7,1,8,9,6,2,3,9,8,6,3,2,7,4,1,5},{7,1,8,9,6,2,3,9,8,6,3,2,7,4,5,1},{7,1,8,9,6,2,3,9,8,6,3,2,7,5,1,4},
{7,1,8,9,6,2,3,9,8,6,3,2,7,5,4,1},{7,1,8,9,6,3,2,6,8,9,2,3,7,1,4,5},{7,1,8,9,6,3,2,6,8,9,2,7,3,1,4,5},{7,1,8,9,6,3,2,6,8,9,2,7,3,1,5,4},
{7,1,8,9,6,3,2,6,8,9,2,7,3,5,1,4},{7,1,8,9,6,3,2,6,8,9,3,2,7,1,5,4},{7,1,8,9,6,3,2,6,8,9,3,7,2,1,4,5},{7,1,8,9,6,3,2,6,8,9,3,7,2,1,5,4},
{7,1,8,9,6,3,2,6,8,9,7,2,3,1,4,5},{7,1,8,9,6,3,2,6,8,9,7,2,3,5,1,4},{7,1,8,9,6,3,2,6,8,9,7,3,2,1,4,5},{7,1,8,9,6,3,2,6,8,9,7,3,2,1,5,4},
{7,1,8,9,6,3,2,6,8,9,7,3,2,5,1,4},{7,1,8,9,6,3,2,6,8,9,7,3,2,5,4,1},{7,1,8,9,6,3,2,6,9,8,2,3,7,1,4,5},{7,1,8,9,6,3,2,6,9,8,2,3,7,1,5,4},
{7,1,8,9,6,3,2,6,9,8,2,3,7,5,1,4},{7,1,8,9,6,3,2,6,9,8,2,7,3,1,4,5},{7,1,8,9,6,3,2,6,9,8,3,2,7,1,4,5},{7,1,8,9,6,3,2,6,9,8,3,2,7,1,5,4},
{7,1,8,9,6,3,2,6,9,8,3,2,7,5,4,1},{7,1,8,9,6,3,2,6,9,8,3,7,2,1,5,4},{7,1,8,9,6,3,2,6,9,8,7,3,2,1,4,5},{7,1,8,9,6,3,2,6,9,8,7,3,2,5,1,4},
{7,1,8,9,6,3,2,8,6,9,2,7,3,1,4,5},{7,1,8,9,6,3,2,8,6,9,3,7,2,1,4,5},{7,1,8,9,6,3,2,8,9,6,2,3,7,1,4,5},{7,1,8,9,6,3,2,8,9,6,2,3,7,4,1,5},
{7,1,8,9,6,3,2,8,9,6,3,2,7,1,4,5},{7,1,8,9,6,3,2,8,9,6,3,2,7,1,5,4},{7,1,8,9,6,3,2,8,9,6,3,2,7,4,5,1},{7,1,8,9,6,3,2,8,9,6,3,2,7,5,4,1},
{7,1,8,9,6,3,2,8,9,6,3,7,2,1,4,5},{7,1,8,9,6,3,2,8,9,6,3,7,2,1,5,4},{7,1,8,9,6,3,2,8,9,6,3,7,2,4,5,1},{7,1,8,9,6,3,2,9,6,8,3,2,7,1,4,5},
{7,1,8,9,6,3,2,9,6,8,3,2,7,1,5,4},{7,1,8,9,6,3,2,9,6,8,3,2,7,4,5,1},{7,1,8,9,6,3,2,9,8,6,3,2,7,1,4,5},{7,2,8,9,1,6,3,6,8,9,1,7,3,4,5,2},
{7,2,8,9,1,6,3,6,8,9,7,1,3,2,5,4},{7,2,8,9,1,6,3,6,9,8,1,3,7,4,2,5},{7,2,8,9,1,6,3,6,9,8,1,3,7,5,2,4},{7,2,8,9,1,6,3,6,9,8,3,1,7,2,5,4},
{7,2,8,9,1,6,3,6,9,8,3,1,7,5,2,4},{7,2,8,9,1,6,3,6,9,8,7,1,3,2,5,4},{7,2,8,9,1,6,3,8,6,9,7,1,3,2,4,5},{7,2,8,9,1,6,3,8,6,9,7,3,1,2,4,5},
{7,2,8,9,1,6,3,8,6,9,7,3,1,5,2,4},{7,2,8,9,1,6,3,8,9,6,3,1,7,2,4,5},{7,2,8,9,1,6,3,8,9,6,7,3,1,5,2,4},{7,2,8,9,6,1,3,6,8,9,1,7,3,2,4,5},
{7,2,8,9,6,1,3,6,8,9,7,1,3,2,4,5},{7,2,8,9,6,1,3,6,8,9,7,1,3,2,5,4},{7,2,8,9,6,1,3,6,9,8,1,3,7,2,5,4},{7,2,8,9,6,1,3,6,9,8,3,1,7,2,4,5},
{7,2,8,9,6,1,3,6,9,8,3,1,7,2,5,4},{7,2,8,9,6,1,3,6,9,8,7,1,3,2,4,5},{7,2,8,9,6,1,3,8,6,9,7,1,3,2,4,5},{7,2,8,9,6,1,3,8,6,9,7,3,1,2,4,5},
{7,2,8,9,6,1,3,8,6,9,7,3,1,2,5,4},{7,2,8,9,6,1,3,8,9,6,1,3,7,2,4,5},{7,2,8,9,6,1,3,8,9,6,1,3,7,2,5,4},{7,2,8,9,6,1,3,8,9,6,3,1,7,2,4,5},
{7,2,8,9,6,1,3,8,9,6,3,1,7,4,2,5},{7,2,8,9,6,1,3,8,9,6,7,3,1,2,4,5},{7,2,8,9,6,1,3,8,9,6,7,3,1,2,5,4},{7,2,8,9,6,1,3,9,6,8,1,3,7,2,4,5},
{7,2,8,9,6,1,3,9,6,8,1,3,7,2,5,4},{7,2,8,9,6,1,3,9,6,8,7,3,1,2,4,5},{7,2,8,9,6,1,3,9,8,6,1,3,7,2,4,5},{7,2,8,9,6,3,1,6,8,9,1,7,3,2,4,5},
{7,2,8,9,6,3,1,6,8,9,7,1,3,2,5,4},{7,2,8,9,6,3,1,6,9,8,3,1,7,2,5,4},{7,2,8,9,6,3,1,8,6,9,7,1,3,2,4,5},{7,2,8,9,6,3,1,8,6,9,7,1,3,2,5,4},
{7,2,8,9,6,3,1,8,6,9,7,3,1,2,4,5},{7,2,8,9,6,3,1,8,6,9,7,3,1,2,5,4},{7,2,8,9,6,3,1,8,9,6,1,3,7,2,4,5},{7,2,8,9,6,3,1,8,9,6,1,3,7,2,5,4},
{7,2,8,9,6,3,1,8,9,6,1,3,7,4,2,5},{7,2,8,9,6,3,1,8,9,6,3,1,7,2,4,5},{7,2,8,9,6,3,1,8,9,6,3,1,7,2,5,4},{7,2,8,9,6,3,1,8,9,6,7,3,1,2,4,5},
{7,2,8,9,6,3,1,9,6,8,1,3,7,2,5,4},{7,2,8,9,6,3,1,9,6,8,7,3,1,2,4,5},{7,2,8,9,6,3,1,9,8,6,1,3,7,2,4,5},{7,3,8,9,6,1,2,8,9,6,1,2,7,3,5,4},
{7,3,8,9,6,1,2,8,9,6,1,7,2,3,5,4},{7,3,8,9,6,1,2,8,9,6,2,7,1,3,5,4},{7,3,8,9,6,1,2,8,9,6,7,2,1,3,5,4},{7,3,8,9,6,2,1,8,9,6,2,1,7,3,5,4},
{7,8,9,3,6,1,2,9,8,6,2,1,7,3,5,4},
};

static int binarySearch416(const void *value)
{
	int left = 0, right = 400, mid, comp;

	while (left <= right) {
        mid = (right-left)/2 + left;
		comp = memcmp(value, bandPrefix416[mid], 16);
        if (comp == 0)
            return mid;
        if (comp < 0)
            right = mid - 1;
        else
            left = mid + 1;
	}
    return -1;
}

static const char v12345678945[11] = {1,2,3,4,5,6,7,8,9,4,5};
static const int fact[9] =
{
	1,
	1*2,
	1*2*3,
	1*2*3*4,
	1*2*3*4*5,
	1*2*3*4*5*6,
	1*2*3*4*5*6*7,
	1*2*3*4*5*6*7*8,
	1*2*3*4*5*6*7*8*9
};

static inline void sortChar(char *t, int size) {
	char c;
	int i, j, again = 1;
	for(i = 0; again && (i < size - 1); i++) {
		again = 0;
		for(j = 0; j < size - i - 1; j++) {
			if(t[j + 1] < t[j]) {
				c = t[j + 1];
				t[j + 1] = t[j];
				t[j] = c;
				again = 1;
			}
		}
	}
}

static inline int gr2fact(char *t, int base) {
	int res = 0, i, j;
	for(i = 0; i < base - 1; i++) {
		res += t[i] * fact[base - i - 2];
		for(j = i + 1; j < base; j++) //normalize the rest to 0..(base-i)
			if(t[j] > t[i])
				t[j] = t[j] - 1;
	}
	return res;
}

static inline void fact2gr(int f, char *t, int base) {
	int i, j;
	t[base - 1] = 0;
	for(i = 0; i < base - 1; i++) {
		t[i] = f / fact[base - i - 2];
		f %= fact[base - i - 2];
	}
	for(i = base - 2; i >= 0; i--) {
		for(j = i + 1; j < base; j++)
			if(t[i] <= t[j])
				t[j] = t[j] + 1;
	}
}
static const char perm3[6][3] = {{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,0,1},{2,1,0}};

void fact2gr3(int f, char *t) {
	int i;
	for(i = 0; i < 3; i++)
		t[i] = perm3[f][i];
}

//uncompress the binary grid (81 * 0x01..0x09)
extern int uncomprGrid(char *g, const char *cg) {
	int i, j;
	unsigned int u, n;
	char t[9];

	int band416index;
	int row4;
	int row56[3];
	int row789[8];

	//1) Check version
	if(cg[0] & 0x80) return -1; //error

	//2) Uncompress the bitfields to integers
	n = 0;
	u = cg[9];
	for(i = 77; i < 80; i++)  n <<= 1, n |= u & 1, u >>= 1;
	row789[7] = n; n = 0;
	for(i = 74; i < 77; i++)  n <<= 1, n |= u & 1, u >>= 1;
	row789[6] = n; n = 0;
	for(i = 72; i < 74; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = cg[8];
	for(i = 71; i < 72; i++)  n <<= 1, n |= u & 1, u >>= 1;
	row789[5] = n; n = 0;
	for(i = 68; i < 71; i++)  n <<= 1, n |= u & 1, u >>= 1;
	row789[4] = n; n = 0;
	for(i = 65; i < 68; i++)  n <<= 1, n |= u & 1, u >>= 1;
	row789[3] = n; n = 0;
	for(i = 64; i < 65; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = cg[7];
	for(i = 62; i < 64; i++)  n <<= 1, n |= u & 1, u >>= 1;
	row789[2] = n; n = 0;
	for(i = 59; i < 62; i++)  n <<= 1, n |= u & 1, u >>= 1;
	row789[1] = n; n = 0;
	for(i = 56; i < 59; i++)  n <<= 1, n |= u & 1, u >>= 1;
	row789[0] = n; n = 0;
	u = cg[6];
	for(i = 48; i < 56; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = cg[5];
	for(i = 46; i < 48; i++)  n <<= 1, n |= u & 1, u >>= 1;
	row56[2] = n; n = 0;
	for(i = 40; i < 46; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = cg[4];
	for(i = 36; i < 40; i++)  n <<= 1, n |= u & 1, u >>= 1;
	row56[1] = n; n = 0;
	for(i = 32; i < 36; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = cg[3];
	for(i = 26; i < 32; i++)  n <<= 1, n |= u & 1, u >>= 1;
	row56[0] = n; n = 0;
	for(i = 24; i < 26; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = cg[2];
	for(i = 16; i < 24; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = cg[1];
	for(i = 10; i < 16; i++)  n <<= 1, n |= u & 1, u >>= 1;
	row4 = n; n = 0;
	for(i = 8; i < 10; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = cg[0];
	for(i = 1; i < 8; i++)  n <<= 1, n |= u & 1, u >>= 1;
	band416index = n;

	//3) Uncompress rows 1, 2, 3
	if(band416index < 0) return -1;
	if(band416index > 400) return -1;
	memcpy(g, v12345678945, 11);
	memcpy(&g[11], bandPrefix416[band416index], 16);

	//4) Uncompress row 4
	g[27] = 2;
	if(row4 > fact[8]) return -1;
	if(row4 < 0) return -1;
	fact2gr(row4, t, 8);
	for(i = 28, j = 0; i <= 35; i++, j++) {
		g[i] = t[j] + 1;
		if(g[i] == 2) {
			g[i] = 9;
		}
	}
	//5) Uncompress rows 5, 6 based on boxes and row 4
	for(i = 0; i < 3; i++) { //box
		if(row56[i] > fact[6]) return -1;
		if(row56[i] < 0) return -1;
		fact2gr(row56[i], t + 3, 6);
		t[0] = g[27 + i * 3] - 1;
		t[1] = g[28 + i * 3] - 1;
		t[2] = g[29 + i * 3] - 1;
		sortChar(t, 3);
		for(j = 3; j < 9; j++) if(t[j] >= t[0]) t[j]++;
		for(j = 3; j < 9; j++) if(t[j] >= t[1]) t[j]++;
		for(j = 3; j < 9; j++) if(t[j] >= t[2]) t[j]++;
		g[36 + i * 3] = t[3] + 1;
		g[37 + i * 3] = t[4] + 1;
		g[38 + i * 3] = t[5] + 1;
		g[45 + i * 3] = t[6] + 1;
		g[46 + i * 3] = t[7] + 1;
		g[47 + i * 3] = t[8] + 1;
	}
	//6) Uncompress rows 7, 8, 9 by columns
	for(i = 0; i < 8; i++) { //skip the last column
		if(row789[i] > fact[3]) return -1;
		if(row789[i] < 0) return -1;
		fact2gr3(row789[i], t + 6);
		t[0] = g[0 + i] - 1;
		t[1] = g[9 + i] - 1;
		t[2] = g[18 + i] - 1;
		t[3] = g[27 + i] - 1;
		t[4] = g[36 + i] - 1;
		t[5] = g[45 + i] - 1;
		sortChar(t, 6);
		for(j = 6; j < 9; j++) if(t[j] >= t[0]) t[j]++;
		for(j = 6; j < 9; j++) if(t[j] >= t[1]) t[j]++;
		for(j = 6; j < 9; j++) if(t[j] >= t[2]) t[j]++;
		for(j = 6; j < 9; j++) if(t[j] >= t[3]) t[j]++;
		for(j = 6; j < 9; j++) if(t[j] >= t[4]) t[j]++;
		for(j = 6; j < 9; j++) if(t[j] >= t[5]) t[j]++;
		g[54 + i] = t[6] + 1;
		g[63 + i] = t[7] + 1;
		g[72 + i] = t[8] + 1;
	}
	//7) Find the values in rows 8, 9 column 9 based on the rest values in the row
	g[62] = 1+2+3+4+5+6+7+8+9-g[54]-g[55]-g[56]-g[57]-g[58]-g[59]-g[60]-g[61];
	g[71] = 1+2+3+4+5+6+7+8+9-g[63]-g[64]-g[65]-g[66]-g[67]-g[68]-g[69]-g[70];
	g[80] = 1+2+3+4+5+6+7+8+9-g[72]-g[73]-g[74]-g[75]-g[76]-g[77]-g[78]-g[79];
	//8) Check the consistency (TODO)
	
	return 0;
}

//compress the binary grid (81 * 0x01..0x09 -> cg[10])
extern int comprGrid(const char *g, char *cg) {
	int i, j;
	unsigned int u, n;
	char t[9];

	int band416index;
	int row4;
	int row56[3];
	int row789[8];

	//<---1---><---2---><---3---><---4---><---5---><---6---><---7---><---8---><---9--->
	//12345678945xxxxxxxxxxxxxxxx2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
	//012345678901234567890123456789012345678901234567890123456789012345678901234567890
	//0         1         2         3         4         5         6         7         8
	//<------------9-------------><--16--><-------30-------><-----------24-----------> =79 bits (416 lup, 8!, 3*6!, 9*3!)

	//1) Check whether the pattern looks like minlex normalized
	if(memcmp(g, v12345678945, 11)) return 1; //error
	if(g[27] != 2) return 1; //error

	//2) Find the index of the first band
	band416index = binarySearch416(&(g[11]));
	if(band416index == -1)	return 1; //error

	//3) Compress row 4 as 8! possibilities
	//3.1 replace '9' with '2'
	for(i = 28, j = 0; i <= 35; i++, j++) {
		t[j] = g[i] - 1;
		if(t[j] == 8) {
			t[j] = 1;
		}
	}
	//3.2 Compress as one of the 8! possibilities (max = 0x9D7F = 16 bits)
	row4 = gr2fact(t, 8);
	//fact2gr(row4, t, 8);

	//4) Compress rows 5 and 6 based on row 4
	for(i = 0; i < 3; i++) { //box
	//4.1 Prepare data for box processing
		//row 4
		t[0] = g[27 + i * 3] - 1;
		t[1] = g[28 + i * 3] - 1;
		t[2] = g[29 + i * 3] - 1;
		//row 5
		t[3] = g[36 + i * 3] - 1;
		t[4] = g[37 + i * 3] - 1;
		t[5] = g[38 + i * 3] - 1;
		//row 6
		t[6] = g[45 + i * 3] - 1;
		t[7] = g[46 + i * 3] - 1;
		t[8] = g[47 + i * 3] - 1;
		//4.2 Normalize t[3..8] to values 0..5
		for(j = 3; j < 9; j++) {
			n = 0;
			if(t[j] > t[0]) n = 1;
			if(t[j] > t[1]) n++;
			if(t[j] > t[2]) n++;
			t[j] -= n;
		}
		//4.3 Compress rows 5, 6 in the box as one of 6! possibilities (max = 0x2D0 = 10 bits)
		row56[i] = gr2fact(t + 3, 6);
	}
	//5) Compress rows 7, 8, 9 by columns
	for(i = 0; i < 8; i++) { //skip the last column
		//5.1 Prepare the data by columns
		t[0] = g[0 + i] - 1;
		t[1] = g[9 + i] - 1;
		t[2] = g[18 + i] - 1;
		t[3] = g[27 + i] - 1;
		t[4] = g[36 + i] - 1;
		t[5] = g[45 + i] - 1;
		t[6] = g[54 + i] - 1;
		t[7] = g[63 + i] - 1;
		t[8] = g[72 + i] - 1;
		//5.2 Normalize t[6..8] to values 0..3
		for(j = 6; j < 9; j++) {
			n = 0;
			if(t[j] > t[0]) n = 1;
			if(t[j] > t[1]) n++;
			if(t[j] > t[2]) n++;
			if(t[j] > t[3]) n++;
			if(t[j] > t[4]) n++;
			if(t[j] > t[5]) n++;
			t[j] -= n;
		}
		//5.3. Compress rows 7, 8, 9 in the column as one of 3! possibilities (max = 6 = 3 bits)
		row789[i] = gr2fact(t + 6, 3);
	}
	//6) Arrange the compressed data into an 80 bit binary field
	//012345678901234567890123456789012345678901234567890123456789012345678901234567890
	//0         1         2         3         4         5         6         7         8
	//v<-b416i-><-----row4-----><-r56[0]-><-r56[1]-><-r56[2]-><--------row789---------> =80 bits (1 + 416lup, 8!, 3*6!, 8*3!)
	//<===0==><===1==><===2==><===3==><===4==><===5==><===6==><===7==><===8==><===9==>

	//bits		size	value
	//=======================
	//0			1		version = 0
	//1..9		9		band416index
	//10..25	16		row4
	//26..35	10		row56[0]
	//36..45	10		row56[1]
	//46..55	10		row56[2]
	//56..58	3		row789[0]
	//59..61	3		row789[1]
	//62..64	3		row789[2]
	//65..67	3		row789[3]
	//68..70	3		row789[4]
	//71..73	3		row789[5]
	//74..76	3		row789[6]
	//77..79	3		row789[7]

	n = 0; //version
	u = (unsigned int)band416index;
	for(i = 1; i < 8; i++)  n <<= 1, n |= u & 1, u >>= 1;
	cg[0] = n;
	for(i = 8; i < 10; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = (unsigned int)row4; //00 00011001 010010
	for(i = 10; i < 16; i++)  n <<= 1, n |= u & 1, u >>= 1;
	cg[1] = n;
	for(i = 16; i < 24; i++)  n <<= 1, n |= u & 1, u >>= 1;
	cg[2] = n;
	for(i = 24; i < 26; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = (unsigned int)row56[0];
	for(i = 26; i < 32; i++)  n <<= 1, n |= u & 1, u >>= 1;
	cg[3] = n;
	for(i = 32; i < 36; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = (unsigned int)row56[1];
	for(i = 36; i < 40; i++)  n <<= 1, n |= u & 1, u >>= 1;
	cg[4] = n;
	for(i = 40; i < 46; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = (unsigned int)row56[2];
	for(i = 46; i < 48; i++)  n <<= 1, n |= u & 1, u >>= 1;
	cg[5] = n;
	for(i = 48; i < 56; i++)  n <<= 1, n |= u & 1, u >>= 1;
	cg[6] = n;
	u = (unsigned int)row789[0];
	for(i = 56; i < 59; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = (unsigned int)row789[1];
	for(i = 59; i < 62; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = (unsigned int)row789[2];
	for(i = 62; i < 64; i++)  n <<= 1, n |= u & 1, u >>= 1;
	cg[7] = n;
	for(i = 64; i < 65; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = (unsigned int)row789[3];
	for(i = 65; i < 68; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = (unsigned int)row789[4];
	for(i = 68; i < 71; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = (unsigned int)row789[5];
	for(i = 71; i < 72; i++)  n <<= 1, n |= u & 1, u >>= 1;
	cg[8] = n;
	for(i = 72; i < 74; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = (unsigned int)row789[6];
	for(i = 74; i < 77; i++)  n <<= 1, n |= u & 1, u >>= 1;
	u = (unsigned int)row789[7];
	for(i = 77; i < 80; i++)  n <<= 1, n |= u & 1, u >>= 1;
	cg[9] = n;

	return 0;
}

//extract, uncompress, and convert to 81 * '1'..'9' the grid by given 0-based index
extern int gridByIndex(FILE *catalog, const unsigned long long index, char *g) {
	char cg[10];
	fpos_t fpos = index * 10; //10 bytes/record
	if(fsetpos(catalog, &fpos)) return -1;
	if(fread(cg, 10, 1, catalog) != 1) return -1;
	if(uncomprGrid(g, cg)) return -1;
	return 0;
}

//canonicalize, compress, and find 0-based index of the given '0'-based grid within the ordered catalog
extern int gridIndex(FILE *catalog, unsigned long long index, const char *g) {
	char cg[10];
	char gr[81];
	char grminlex[81];
	for(int i = 0; i < 81; i++) { //map '1' to 1
		gr[i] = g[i] - '0';
	}
	rowminlex(gr, grminlex); //canonicalize
	if(comprGrid(grminlex, cg)) return -1; //compress

	//TODO: perform binary search for cg record in the catalog
	//TODO: search within appropriate band only
	index = -1;

	return 0; //no error
}
